package com.prtek.reminder.presenter;

import android.content.Context;
import android.os.Bundle;
import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.LexiconListener;
import com.iflytek.cloud.RecognizerListener;
import com.iflytek.cloud.RecognizerResult;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechRecognizer;
import com.iflytek.cloud.util.UserWords;
import com.prtek.iis.grammar.Expression;
import com.prtek.reminder.Constant;
import com.prtek.reminder.bean.Notes;
import com.prtek.reminder.bean.NotesJoinUser;
import com.prtek.reminder.bean.User;
import com.prtek.reminder.model.ReminderDao;
import com.prtek.reminder.model.SpeechEventModel;
import com.prtek.reminder.model.UserManager;
import com.prtek.reminder.util.FileUtils;
import com.prtek.reminder.util.JsonParser;
import com.prtek.reminder.util.LogUtil;
import com.prtek.reminder.view.RemindEditView;
import java.io.File;
import java.util.ArrayList;

import static com.prtek.reminder.Constant.TYPE_AUDIO;
import static com.prtek.reminder.Constant.TYPE_DATE;
import static com.prtek.reminder.Constant.TYPE_DESC;
import static com.prtek.reminder.Constant.TYPE_USER;

/**
 * Created by jarly on 2018/10/23.
 */

public class RemindEditPresenterImpl
    implements RemindEditPresenter, SpeechEventModel.SpeechResultEditListener {

  private RemindEditView mView;
  private ReminderDao mReminderDao;
  private SpeechEventModel mSpeechEventModel;
  private Context mContext;
  private SpeechRecognizer mRecognizer;
  private int ret;
  private int mSpeechType;
  private StringBuilder mSpeechResult;
  private ArrayList<User> mUserList;

  public RemindEditPresenterImpl(RemindEditView view, ReminderDao reminderDao,
      SpeechEventModel speechEventModel) {
    mView = view;
    mReminderDao = reminderDao;
    mSpeechEventModel = speechEventModel;
  }

  @Override public void start(Context context) {
    mContext = context;
    mRecognizer = SpeechRecognizer.createRecognizer(mContext, mInitListener);
    mSpeechResult = new StringBuilder();
    if (mRecognizer == null) {
      return;
    }
    mUserList = UserManager.getUserList();
    UserWords userWords = new UserWords();

    for (User user : mUserList) {
      userWords.putWord(user.getName());
    }
    mRecognizer.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);
    mRecognizer.setParameter(SpeechConstant.TEXT_ENCODING, "utf-8");
    ret = mRecognizer.updateLexicon("userword", userWords.toString(), new LexiconListener() {
      @Override public void onLexiconUpdated(String s, SpeechError error) {
        if (error != null) {
          LogUtil.e(error.toString());
        } else {
          LogUtil.e("success");
        }
      }
    });
    if (ret != ErrorCode.SUCCESS) mView.showTip("上传热词失败,错误码：" + ret);
  }

  private InitListener mInitListener = code -> {
    if (code != ErrorCode.SUCCESS) {
      mView.showTip("初始化失败，错误码：" + code);
    }
  };

  public void setParam(String vadEos, String asrPtt, String asrPath) {
    if (mRecognizer == null) {
      return;
    }
    mView.stopPlayer();
    mRecognizer.setParameter(SpeechConstant.PARAMS, null);
    // 设置引擎
    mRecognizer.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);
    // 设置返回结果格式
    mRecognizer.setParameter(SpeechConstant.RESULT_TYPE, "json");
    mRecognizer.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
    // 设置语言区域
    mRecognizer.setParameter(SpeechConstant.ACCENT, "zh_cn");

    // 设置语音前端点:静音超时时间，即用户多长时间不说话则当做超时处理
    mRecognizer.setParameter(SpeechConstant.VAD_BOS, "4000");

    // 设置语音后端点:后端点静音检测时间，即用户停止说话多长时间内即认为不再输入， 自动停止录音
    mRecognizer.setParameter(SpeechConstant.VAD_EOS, vadEos);

    // 设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点
    mRecognizer.setParameter(SpeechConstant.ASR_PTT, asrPtt);

    mRecognizer.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
    mRecognizer.setParameter(SpeechConstant.ASR_AUDIO_PATH, asrPath);
    if (mSpeechType == Constant.TYPE_AUDIO) {
      mRecognizer.setParameter(SpeechConstant.AUDIO_SOURCE, "-1");
    }
  }

  public void startRecognizer(File asrFile) {
    ret = mRecognizer.startListening(mRecognizerListener);

    if (ret != ErrorCode.SUCCESS) {
      mView.showTip("听写失败,错误码：" + ret);
      return;
    }

    if (asrFile == null) {
      return;
    }

    final byte[] audioData = FileUtils.readFile(asrFile);
    if (audioData != null) {
      mRecognizer.writeAudio(audioData, 0, audioData.length);
      mRecognizer.stopListening();
    } else {
      mRecognizer.cancel();
      LogUtil.e("read audiorecord file failed!");
    }
  }

  @Override public void setSpeechType(int speechType) {
    mSpeechType = speechType;
  }

  private RecognizerListener mRecognizerListener = new RecognizerListener() {

    @Override public void onBeginOfSpeech() {
      mView.showTip("开始说话");
      mSpeechResult.delete(0, mSpeechResult.length());
    }

    @Override public void onEndOfSpeech() {
      mView.showTip("结束说话");
    }

    @Override public void onResult(RecognizerResult results, boolean isLast) {

      final String result = JsonParser.parseIatResult(results.getResultString());
      mSpeechResult.append(result);
      switch (mSpeechType) {
        case TYPE_DESC:
          mView.setDescText(result);
          break;
        case TYPE_USER:
          mView.addSelectUser(result);
          break;
        case TYPE_AUDIO:
          mView.setAudioText(mSpeechResult.toString());
          break;
        case TYPE_DATE:
          mView.setDateText(mSpeechResult.toString());
          break;
        default:
          break;
      }
    }

    @Override public void onError(SpeechError error) {
      mView.showTip(error.getPlainDescription(true));
    }

    @Override public void onVolumeChanged(int volume, byte[] data) {
      mView.showTip("当前正在说话，音量大小：" + volume);
    }

    @Override public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
    }
  };

  @Override public void setupSpeechEventListener(Context context, Expression expression) {
    mSpeechEventModel.setupSpeechEventListener(context, expression);
    mSpeechEventModel.setSpeechResultEditListener(this);
  }

  @Override public void removeSpeechEventListener() {
    mSpeechEventModel.removeSpeechEventListener();
  }

  @Override public void saveNotes(Notes notes) {
    mReminderDao.insertNotes(notes);
  }

  @Override public void addNotesJoinUser(NotesJoinUser joinUser) {
    mReminderDao.addNotesJoinUser(joinUser);
  }

  @Override public void destroy() {
    if (mRecognizer != null) {
      mRecognizer.destroy();
    }
    mView = null;
  }

  @Override public void remindAudio() {
    mView.remindAudio();
  }

  @Override public void remindDate() {
    mView.remindDate();
  }

  @Override public void remindDesc() {
    mView.remindDesc();
  }

  @Override public void remindSave() {
    mView.remindSave();
  }

  @Override public void remindCancel() {
    mView.remindCancel();
  }

  @Override public void remindConfirm() {
    mView.remindConfirm();
  }

  @Override public void addSelectUser(String name) {
    mView.addSelectUser(name);
  }

  @Override public void selectUser() {
    mView.selectUser();
  }
}
